package cn.lixunims.ims.modular;

import cn.lixunims.common.pojo.CommonResult;
import cn.lixunims.ims.modular.basics.entity.ImsCustomer;
import cn.lixunims.ims.modular.basics.entity.ImsSupplier;
import cn.lixunims.ims.modular.basics.service.impl.ImsCustomerServiceImpl;
import cn.lixunims.ims.modular.basics.service.impl.ImsSupplierServiceImpl;
import cn.lixunims.ims.modular.bill.entity.ImsBillDetail;
import cn.lixunims.ims.modular.bill.entity.ImsBillHeader;
import cn.lixunims.ims.modular.bill.mapper.ImsBillHeaderMapper;
import cn.lixunims.ims.modular.bill.service.impl.ImsBillDetailServiceImpl;
import cn.lixunims.ims.modular.bill.service.impl.ImsBillHeaderServiceImpl;
import cn.lixunims.ims.modular.inventory.entity.ImsInventoryChangeLog;
import cn.lixunims.ims.modular.inventory.entity.ImsInventoryCheck;
import cn.lixunims.ims.modular.inventory.entity.ImsInventoryCheckDetail;
import cn.lixunims.ims.modular.inventory.entity.ImsRealTimeInventory;
import cn.lixunims.ims.modular.inventory.mapper.ImsInventoryCheckDetailMapper;
import cn.lixunims.ims.modular.inventory.mapper.ImsInventoryCheckMapper;
import cn.lixunims.ims.modular.inventory.service.impl.ImsInventoryChangeLogServiceImpl;
import cn.lixunims.ims.modular.inventory.service.impl.ImsInventoryCheckDetailServiceImpl;
import cn.lixunims.ims.modular.inventory.service.impl.ImsInventoryCheckServiceImpl;
import cn.lixunims.ims.modular.inventory.service.impl.ImsRealTimeInventoryServiceImpl;
import cn.lixunims.ims.modular.order.entity.ImsOrderHeader;
import cn.lixunims.ims.modular.order.mapper.ImsOrderHeaderMapper;
import cn.lixunims.ims.modular.order.service.impl.ImsOrderDetailServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * 后台首页统计
 * @author YouDong
 * @date 2024/10/22
 */
@Tag(name = "首页统计控制器")
@RestController
@Slf4j
public class IndexController {


    private final ImsBillHeaderServiceImpl imsBillHeaderServiceImpl;
    private final ImsBillDetailServiceImpl imsBillDetailServiceImpl;
    private final ImsRealTimeInventoryServiceImpl imsRealTimeInventoryServiceImpl;
    private final ImsInventoryChangeLogServiceImpl imsInventoryChangeLogServiceImpl;
    private final ImsInventoryCheckDetailServiceImpl imsInventoryCheckDetailServiceImpl;
    private final ImsCustomerServiceImpl imsCustomerServiceImpl;
    private final ImsSupplierServiceImpl imsSupplierServiceImpl;
    private final ImsOrderDetailServiceImpl imsOrderDetailServiceImpl;
    private final ImsBillHeaderMapper imsBillHeaderMapper;
    private final ImsOrderHeaderMapper imsOrderHeaderMapper;
    private final ImsInventoryCheckServiceImpl imsInventoryCheckServiceImpl;
    private final ImsInventoryCheckMapper imsInventoryCheckMapper;
    private final ImsInventoryCheckDetailMapper imsInventoryCheckDetailMapper;

    public IndexController(ImsBillHeaderServiceImpl imsBillHeaderServiceImpl, ImsBillDetailServiceImpl imsBillDetailServiceImpl, ImsRealTimeInventoryServiceImpl imsRealTimeInventoryServiceImpl, ImsInventoryChangeLogServiceImpl imsInventoryChangeLogServiceImpl, ImsInventoryCheckDetailServiceImpl imsInventoryCheckDetailServiceImpl, ImsCustomerServiceImpl imsCustomerServiceImpl, ImsSupplierServiceImpl imsSupplierServiceImpl, ImsOrderDetailServiceImpl imsOrderDetailServiceImpl, ImsBillHeaderMapper imsBillHeaderMapper, ImsOrderHeaderMapper imsOrderHeaderMapper, ImsInventoryCheckServiceImpl imsInventoryCheckServiceImpl, ImsInventoryCheckMapper imsInventoryCheckMapper, ImsInventoryCheckDetailMapper imsInventoryCheckDetailMapper) {
        this.imsBillHeaderServiceImpl = imsBillHeaderServiceImpl;
        this.imsBillDetailServiceImpl = imsBillDetailServiceImpl;
        this.imsRealTimeInventoryServiceImpl = imsRealTimeInventoryServiceImpl;
        this.imsInventoryChangeLogServiceImpl = imsInventoryChangeLogServiceImpl;
        this.imsInventoryCheckDetailServiceImpl = imsInventoryCheckDetailServiceImpl;
        this.imsCustomerServiceImpl = imsCustomerServiceImpl;
        this.imsSupplierServiceImpl = imsSupplierServiceImpl;
        this.imsOrderDetailServiceImpl = imsOrderDetailServiceImpl;
        this.imsBillHeaderMapper = imsBillHeaderMapper;
        this.imsOrderHeaderMapper = imsOrderHeaderMapper;
        this.imsInventoryCheckServiceImpl = imsInventoryCheckServiceImpl;
        this.imsInventoryCheckMapper = imsInventoryCheckMapper;
        this.imsInventoryCheckDetailMapper = imsInventoryCheckDetailMapper;
    }

    /**
     * 首页统计
     */
    @Operation(summary = "首页统计")
    @GetMapping(value = "/ims/index")
    public CommonResult index() throws ExecutionException {

        // 采购金额
        // 采购金额
        CompletableFuture<BigDecimal> future1 = CompletableFuture.supplyAsync(() -> {
            // 获取采购入库单据
            List<ImsBillHeader> cgrk = imsBillHeaderServiceImpl.lambdaQuery()
                    .eq(ImsBillHeader::getBillType, "采购入库")
                    .eq(ImsBillHeader::getBillStatus, "1")
                    .list();
            List<String> headerIds = cgrk.stream().map(ImsBillHeader::getBillId).collect(Collectors.toList());

            if (headerIds.isEmpty()) {
                return BigDecimal.ZERO;
            }

            // 获取采购明细
            List<ImsBillDetail> list = imsBillDetailServiceImpl.lambdaQuery().in(ImsBillDetail::getBillId, headerIds).list();

            // 获取库存盘点数据
            List<ImsInventoryCheckDetail> inventoryCheckDetails = imsInventoryCheckDetailServiceImpl.lambdaQuery()
                    .list(); // 可以根据需要添加筛选条件

            // 计算缺少和多余库存
            Map<String, Long> inventoryAdjustments = new HashMap<>();
            for (ImsInventoryCheckDetail checkDetail : inventoryCheckDetails) {
                String productId = checkDetail.getProductId();
                long smallCount = checkDetail.getSmallCount(); // 缺少库存
                long bigCount = checkDetail.getBigCount(); // 多余库存

                // 更新库存调整 Map，直接计算缺少和多余
                inventoryAdjustments.put(productId, inventoryAdjustments.getOrDefault(productId, 0L) + smallCount - bigCount);
            }

            // 根据所有的ImsBillDetail的univalence乘以planQuantity求和
            BigDecimal totalPurchasingAmount = list.stream()
                    .map(imsBillDetail -> {
                        BigDecimal amount = imsBillDetail.getUnivalence().multiply(new BigDecimal(imsBillDetail.getPlanQuantity()));

                        // 调整金额
                        String productId = imsBillDetail.getProductId();
                        Long adjustment = inventoryAdjustments.get(productId); // 获取当前商品的调整值

                        // 如果库存缺少，增加采购金额
                        if (adjustment != null) {
                            // 只增加缺少部分的采购金额
                            amount = amount.add(imsBillDetail.getUnivalence().multiply(new BigDecimal(-adjustment))); // -adjustment是缺少的数量
                        }
                        return amount;
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            return totalPurchasingAmount;
        });



        // 销售金额
        CompletableFuture<BigDecimal> future2 = CompletableFuture.supplyAsync(() -> {
            List<ImsBillHeader> cgrk = imsBillHeaderServiceImpl.lambdaQuery()
                    .eq(ImsBillHeader::getBillStatus, "1")
                    .eq(ImsBillHeader::getBillType, "销售出库").list();
            List<String> headerIds = cgrk.stream().map(ImsBillHeader::getBillId).collect(Collectors.toList());
            if (headerIds.isEmpty()) {
                return new BigDecimal(0);
            }
            List<ImsBillDetail> list = imsBillDetailServiceImpl.lambdaQuery().in(ImsBillDetail::getBillId, headerIds).list();
            // 根据所有的ImsBillDetail的univalence乘以planQuantity求和
            return list.stream().map(imsBillDetail -> imsBillDetail.getUnivalence().multiply(new BigDecimal(imsBillDetail.getPlanQuantity())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        });

        // 库存成本
        CompletableFuture<BigDecimal> future3 = CompletableFuture.supplyAsync(() -> {
            LambdaQueryWrapper<ImsRealTimeInventory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.gt(ImsRealTimeInventory::getCount, 0); // 仅查询库存大于 0 的记录

            // 获取库存记录
            List<ImsRealTimeInventory> inventories = imsRealTimeInventoryServiceImpl.list(queryWrapper);

            // 库存成本 = 库存数量 * 库存成本
            BigDecimal reduce = inventories.stream().map(imsRealTimeInventory -> imsRealTimeInventory.getCost().multiply(new BigDecimal(imsRealTimeInventory.getCount())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 对结果进行四舍五入
            return reduce.setScale(1, BigDecimal.ROUND_HALF_UP);
        });

        // 客户今日，本周，本月，总数
        CompletableFuture<Map<String, Object>> future4 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> result = new HashMap<>();

            // 今日
            long todayCount = imsCustomerServiceImpl.count(
                    new LambdaQueryWrapper<ImsCustomer>()
                            .ge(ImsCustomer::getCreateTime, LocalDate.now().atStartOfDay())
            );

            // 本周
            long weekCount = imsCustomerServiceImpl.count(
                    new LambdaQueryWrapper<ImsCustomer>()
                            .ge(ImsCustomer::getCreateTime, LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay())
            );

            // 本月
            long monthCount = imsCustomerServiceImpl.count(
                    new LambdaQueryWrapper<ImsCustomer>()
                            .ge(ImsCustomer::getCreateTime, LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay())
            );

            // 总数
            long totalCount = imsCustomerServiceImpl.count();

            result.put("todayCount", todayCount);
            result.put("weekCount", weekCount);
            result.put("monthCount", monthCount);
            result.put("totalCount", totalCount);

            return result;
        });

        // 供应商今日、本周、本月、总数
        CompletableFuture<Map<String, Object>> future5 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> result = new HashMap<>();

            // 今日
            long todayCount = imsSupplierServiceImpl.count(
                    new LambdaQueryWrapper<ImsSupplier>()
                            .ge(ImsSupplier::getCreateTime, LocalDate.now().atStartOfDay())
            );

            // 本周
            long weekCount = imsSupplierServiceImpl.count(
                    new LambdaQueryWrapper<ImsSupplier>()
                            .ge(ImsSupplier::getCreateTime, LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay())
            );

            // 本月
            long monthCount = imsSupplierServiceImpl.count(
                    new LambdaQueryWrapper<ImsSupplier>()
                            .ge(ImsSupplier::getCreateTime, LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay())
            );

            // 总数
            long totalCount = imsSupplierServiceImpl.count();

            result.put("todayCount", todayCount);
            result.put("weekCount", weekCount);
            result.put("monthCount", monthCount);
            result.put("totalCount", totalCount);

            return result;
        });

        //  采购订单数量/金额今日、本周、本月
        CompletableFuture<Map<String, Object>> future6 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> result = new HashMap<>();

            // 订单
            // 今日
            BigDecimal todayAmount = sumOrderAmount("采购订单", LocalDate.now().atStartOfDay());
            Long todayCount = sumOrderCount("采购订单", LocalDate.now().atStartOfDay());
            // 本周
            BigDecimal weekAmount = sumOrderAmount("采购订单", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            Long weekCount = sumOrderCount("采购订单", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            // 本月
            BigDecimal monthAmount = sumOrderAmount("采购订单", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());
            Long monthCount = sumOrderCount("采购订单", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());
            // 入库
            BigDecimal todayAmountBill = sumBillAmount("采购入库", LocalDate.now().atStartOfDay());
            Long todayCountBill = sumBillCount("采购入库", LocalDate.now().atStartOfDay());
            // 本周
            BigDecimal weekAmountBill = sumBillAmount("采购入库", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            Long weekCountBill = sumBillCount("采购入库", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            // 本月
            BigDecimal monthAmountBill = sumBillAmount("采购入库", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());
            Long monthCountBill = sumBillCount("采购入库", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());



            result.put("todayCount", todayCount);
            result.put("todayAmount", todayAmount);
            result.put("weekCount", weekCount);
            result.put("weekAmount", weekAmount);
            result.put("monthCount", monthCount);
            result.put("monthAmount", monthAmount);

            result.put("todayCountBill", todayCountBill);
            result.put("todayAmountBill", todayAmountBill);
            result.put("weekCountBill", weekCountBill);
            result.put("weekAmountBill", weekAmountBill);
            result.put("monthCountBill", monthCountBill);
            result.put("monthAmountBill", monthAmountBill);

            return result;
        });


        // 销售订单数量/金额今日、本周、本月
        CompletableFuture<Map<String, Object>> future7 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> result = new HashMap<>();

            // 订单
            // 今日
            BigDecimal todayAmount = sumOrderAmount("销售订单", LocalDate.now().atStartOfDay());
            Long todayCount = sumOrderCount("销售订单", LocalDate.now().atStartOfDay());
            // 本周
            BigDecimal weekAmount = sumOrderAmount("销售订单", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            Long weekCount = sumOrderCount("销售订单", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            // 本月
            BigDecimal monthAmount = sumOrderAmount("销售订单", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());
            Long monthCount = sumOrderCount("销售订单", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());

            // 出库
            // 今日
            BigDecimal todayAmountBill = sumBillAmount("销售出库", LocalDate.now().atStartOfDay());
            Long todayCountBill = sumBillCount("销售出库", LocalDate.now().atStartOfDay());
            // 本周
            BigDecimal weekAmountBill = sumBillAmount("销售出库", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            Long weekCountBill = sumBillCount("销售出库", LocalDate.now().with(DayOfWeek.MONDAY).atStartOfDay());
            // 本月
            BigDecimal monthAmountBill = sumBillAmount("销售出库", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());
            Long monthCountBill = sumBillCount("销售出库", LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay());

            result.put("todayCount", todayCount);
            result.put("todayAmount", todayAmount);
            result.put("weekCount", weekCount);
            result.put("weekAmount", weekAmount);
            result.put("monthCount", monthCount);
            result.put("monthAmount", monthAmount);

            result.put("todayCountBill", todayCountBill);
            result.put("todayAmountBill", todayAmountBill);
            result.put("weekCountBill", weekCountBill);
            result.put("weekAmountBill", weekAmountBill);
            result.put("monthCountBill", monthCountBill);
            result.put("monthAmountBill", monthAmountBill);

            return result;
        });

        // 每月采购，柱状统计图
        CompletableFuture<Map<String, Object>> future8 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> monthlyPurchases = new HashMap<>();

            // 获取当前年份
            int currentYear = LocalDate.now().getYear();
            List<Integer> x = new ArrayList<>();
            List<BigDecimal> y = new ArrayList<>();
            for (int month = 1; month <= 12; month++) {
                LocalDateTime startOfMonth = LocalDate.of(currentYear, month, 1).atStartOfDay();
                LocalDateTime endOfMonth = startOfMonth.plusMonths(1).minusSeconds(1); // 获取当前月最后一秒的时间

                // 查询该月的采购金额
                BigDecimal monthAmount = getMonthlyPurchases("采购入库", startOfMonth, endOfMonth);
                y.add(monthAmount);
                x.add(month);
            }
            monthlyPurchases.put("x", x);
            monthlyPurchases.put("y", y);

            return monthlyPurchases;
        });


        // 每月的销售金额，柱状统计图
        CompletableFuture<Map<String, Object>> future9 = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> monthlySales = new HashMap<>();
            // 获取当前年份
            int currentYear = LocalDate.now().getYear();
            List<Integer> x = new ArrayList<>();
            List<BigDecimal> y = new ArrayList<>();
            List<BigDecimal> profitY = new ArrayList<>();
            for (int month = 1; month <= 12; month++) {
                LocalDateTime startOfMonth = LocalDate.of(currentYear, month, 1).atStartOfDay();
                LocalDateTime endOfMonth = startOfMonth.plusMonths(1).minusSeconds(1); // 获取当前月最后一秒的时间

                // 查询该月的销售金额
                BigDecimal monthAmount = getMonthlyPurchases("销售出库", startOfMonth, endOfMonth);
                y.add(monthAmount);
                x.add(month);


                // 如果monthAmount=0的话
                if (monthAmount.compareTo(BigDecimal.ZERO) != 0) {
                    // TODO 暂时不做毛利润计算毛利润
                    // 查询该月的采购金额
                    BigDecimal monthPurchaseAmount = getMonthlyPurchases("采购入库", startOfMonth, endOfMonth);


                    // 这个月全部的采购金额减去剩余的库存采购金额 = 采购成本
                    BigDecimal inventoryNum = getInventoryNum(startOfMonth, endOfMonth);
                    BigDecimal purchaseMoney = monthPurchaseAmount.subtract(inventoryNum);
                    // 销售金额 减去 采购成本 = 毛利润
                    BigDecimal monthProfit = monthAmount.subtract(purchaseMoney);
                    profitY.add(monthProfit);
                } else {
                    profitY.add(new BigDecimal("0"));
                }



            }
            monthlySales.put("x", x);
            monthlySales.put("y", y);
//            monthlySales.put("profitY", profitY);
            return monthlySales;
        });




        Map<String, Object> result = new HashMap<>();
        try {
            result.put("purchaseMoney", future1.get());
        } catch (Exception e) {
            result.put("purchaseMoney", 0);
            e.printStackTrace();
        }
        try {
            result.put("salesMoney", future2.get());
        } catch (Exception e) {
            result.put("salesMoney", 0);
            e.printStackTrace();
        }
        try {
            result.put("inventoryMoney", future3.get());
        } catch (Exception e) {
            result.put("inventoryMoney", 0);
            e.printStackTrace();
        }
        try {
            Map<String, Object> client = future4.get();
            result.put("client", client);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();
            temp.put("todayCount", 0);
            temp.put("weekCount", 0);
            temp.put("monthCount", 0);
            temp.put("totalCount", 0);
            result.put("client", temp);
            e.printStackTrace();
        }
        try {
            Map<String, Object> supplier = future5.get();
            result.put("supplier", supplier);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();
            temp.put("todayCount", 0);
            temp.put("weekCount", 0);
            temp.put("monthCount", 0);
            temp.put("totalCount", 0);
            result.put("supplier", temp);
            e.printStackTrace();
        }
        try {
            Map<String, Object> purchaseInfo = future6.get();
            result.put("purchaseInfo", purchaseInfo);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();


            temp.put("todayCount", 0);
            temp.put("todayAmount", 0);
            temp.put("weekCount", 0);
            temp.put("weekAmount", 0);
            temp.put("monthCount", 0);
            temp.put("monthAmount", 0);

            temp.put("todayCountBill", 0);
            temp.put("todayAmountBill", 0);
            temp.put("weekCountBill", 0);
            temp.put("weekAmountBill", 0);
            temp.put("monthCountBill", 0);
            temp.put("monthAmountBill", 0);
            result.put("cgxx", temp);
            e.printStackTrace();
        }
        try {
            Map<String, Object> salesInfo = future7.get();
            result.put("salesInfo", salesInfo);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();


            temp.put("todayCount", 0);
            temp.put("todayAmount", 0);
            temp.put("weekCount", 0);
            temp.put("weekAmount", 0);
            temp.put("monthCount", 0);
            temp.put("monthAmount", 0);

            temp.put("todayCountBill", 0);
            temp.put("todayAmountBill", 0);
            temp.put("weekCountBill", 0);
            temp.put("weekAmountBill", 0);
            temp.put("monthCountBill", 0);
            temp.put("monthAmountBill", 0);
            result.put("xxxx", temp);
            e.printStackTrace();
        }
        try {
            Map<String, Object> purchaseStatistics = future8.get();
            result.put("purchaseStatistics", purchaseStatistics);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();
            temp.put("x", new ArrayList<>());
            temp.put("y", new ArrayList<>());
            result.put("purchaseStatistics", temp);
            e.printStackTrace();
        }
        try {
            Map<String, Object> salesStatistics = future9.get();
            result.put("salesStatistics", salesStatistics);
        } catch (Exception e) {
            Map<String, Object> temp = new HashMap<>();
            temp.put("x", new ArrayList<>());
            temp.put("y", new ArrayList<>());
            result.put("salesStatistics", temp);
            e.printStackTrace();
        }


        return CommonResult.data(result);
    }

    /**
     * 获取库存数量
     * @author YouDong
     * @date 2024/10/22
     */
    private @NotNull BigDecimal getInventoryNum( LocalDateTime startOfMonth, LocalDateTime endOfMonth) {
           /*  sql语句
                        SELECT
                inv.ware_id,
                inv.product_id,
                inv.batch_no,
                inv.unit_id,
                inv.supplier_id,
                inv.count AS current_inventory,
                COALESCE((
                    SELECT log.univalence
                    FROM ims_inventory_change_log log
                    WHERE log.ware_id = inv.ware_id
                      AND log.product_id = inv.product_id
                      AND log.operation_type IN ('采购入库', '库存盘点')
                    ORDER BY log.operation_time DESC
                    LIMIT 1
                ), inv.cost) * inv.count AS total_cost
            FROM
                ims_real_time_inventory inv
            WHERE
                inv.count > 0
            ORDER BY
                inv.ware_id, inv.product_id;

            */
        // 查询库存表
        LambdaQueryWrapper<ImsRealTimeInventory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(ImsRealTimeInventory::getCount, 0); // 仅查询库存大于 0 的记录

        // 获取库存记录
        List<ImsRealTimeInventory> inventories = imsRealTimeInventoryServiceImpl.list(queryWrapper);

        // 通过库存结果进一步查询最新的单价，并计算成本
        BigDecimal result = new BigDecimal("0");
        for (ImsRealTimeInventory inv : inventories) {
            // 查询最近的单价记录
            LambdaQueryWrapper<ImsInventoryChangeLog> logQueryWrapper = new LambdaQueryWrapper<>();
            logQueryWrapper.eq(ImsInventoryChangeLog::getWareId, inv.getWareId())
                    .between(startOfMonth!=null, ImsInventoryChangeLog::getOperationTime, startOfMonth,endOfMonth )
                    .eq(ImsInventoryChangeLog::getProductId, inv.getProductId())
                    .in(ImsInventoryChangeLog::getOperationType, Arrays.asList("采购入库", "库存盘点"))
                    .orderByDesc(ImsInventoryChangeLog::getOperationTime);

            ImsInventoryChangeLog latestLog = imsInventoryChangeLogServiceImpl.getOne(logQueryWrapper, false);

            // 计算成本
            BigDecimal cost = latestLog != null ? latestLog.getUnivalence() : inv.getCost();
            BigDecimal totalCost = cost.multiply(new BigDecimal(inv.getCount()));
            log.info("成本：{}", totalCost);
            result = result.add(totalCost);
        }
        return result;
    }

    public BigDecimal sumOrderAmount(String billType, LocalDateTime startTime) {
        // 创建查询包装器
        LambdaQueryWrapper<ImsOrderHeader> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ImsOrderHeader::getBillType, billType)
                .eq(ImsOrderHeader::getBillStatus, "1")
                .ge(ImsOrderHeader::getBillDate, startTime);

        List<ImsOrderHeader> imsOrderHeaders = imsOrderHeaderMapper.selectList(queryWrapper);
        // 如果不为空
        if (imsOrderHeaders.isEmpty()) {
            return BigDecimal.ZERO;
        }

        // 执行查询并求和
        return imsOrderHeaders.stream().map(ImsOrderHeader::getOrderAmount) // 获取每个订单的总金额
                .reduce(BigDecimal.ZERO, BigDecimal::add); // 计算总和
    }
    public Long sumOrderCount(String billType, LocalDateTime startTime) {



        // 创建查询包装器
        LambdaQueryWrapper<ImsOrderHeader> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ImsOrderHeader::getBillType, billType)
                .eq(ImsOrderHeader::getBillStatus, "1")
                .ge(ImsOrderHeader::getBillDate, startTime);

        // 执行查询并求和
        List<ImsOrderHeader> imsBillHeaders = imsOrderHeaderMapper.selectList(queryWrapper);
        if (imsBillHeaders.isEmpty()) {
            return 0L;
        }
        // 获取总和
        return imsBillHeaders.stream().map(ImsOrderHeader::getOrderNum).reduce(Long::sum).get();
    }
    public BigDecimal sumBillAmount(String billType, LocalDateTime startTime) {


        // TODO 暂时这样写，出库先不处理库存盘点
        if (billType.equals("采购入库")) {

            // 获取采购入库单据
            List<ImsBillHeader> cgrk = imsBillHeaderServiceImpl.lambdaQuery()
                    .eq(ImsBillHeader::getBillType, billType)
                    .ge(ImsBillHeader::getBillDate, startTime)
                    .eq(ImsBillHeader::getBillStatus, "1")
                    .list();
            List<String> headerIds = cgrk.stream().map(ImsBillHeader::getBillId).collect(Collectors.toList());

            if (headerIds.isEmpty()) {
                return BigDecimal.ZERO;
            }

            // 获取采购明细
            List<ImsBillDetail> list = imsBillDetailServiceImpl.lambdaQuery().in(ImsBillDetail::getBillId, headerIds).list();

            // 获取库存盘点数据
            List<ImsInventoryCheckDetail> inventoryCheckDetails = imsInventoryCheckDetailServiceImpl.lambdaQuery()
                    .list(); // 可以根据需要添加筛选条件

            // 计算缺少和多余库存
            Map<String, Long> inventoryAdjustments = new HashMap<>();
            for (ImsInventoryCheckDetail checkDetail : inventoryCheckDetails) {
                String productId = checkDetail.getProductId();
                long smallCount = checkDetail.getSmallCount(); // 缺少库存
                long bigCount = checkDetail.getBigCount(); // 多余库存

                // 更新库存调整 Map，直接计算缺少和多余
                inventoryAdjustments.put(productId, inventoryAdjustments.getOrDefault(productId, 0L) + smallCount - bigCount);
            }

            // 根据所有的ImsBillDetail的univalence乘以planQuantity求和
            return list.stream()
                    .map(imsBillDetail -> {
                        BigDecimal amount = imsBillDetail.getUnivalence().multiply(new BigDecimal(imsBillDetail.getPlanQuantity()));

                        // 调整金额
                        String productId = imsBillDetail.getProductId();
                        Long adjustment = inventoryAdjustments.get(productId); // 获取当前商品的调整值

                        // 如果库存缺少，增加采购金额
                        if (adjustment != null) {
                            // 只增加缺少部分的采购金额
                            amount = amount.add(imsBillDetail.getUnivalence().multiply(new BigDecimal(-adjustment))); // -adjustment是缺少的数量
                        }
                        return amount;
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        } else {
            // 创建查询包装器
            LambdaQueryWrapper<ImsBillHeader> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ImsBillHeader::getBillType, billType)
                    .eq(ImsBillHeader::getBillStatus, "1")
                    .ge(ImsBillHeader::getBillDate, startTime);
            List<ImsBillHeader> imsBillHeaders = imsBillHeaderMapper.selectList(queryWrapper);
            // 如果不为空
            if (imsBillHeaders.isEmpty()) {
                return BigDecimal.ZERO;
            }

            // 执行查询并求和
            return imsBillHeaders.stream()
                    .map(ImsBillHeader::getOrderAmount) // 获取每个订单的总金额
                    .reduce(BigDecimal.ZERO, BigDecimal::add); // 计算总和
        }

    }
    public Long sumBillCount(String billType, LocalDateTime startTime) {
        // 创建查询包装器
        LambdaQueryWrapper<ImsBillHeader> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ImsBillHeader::getBillType, billType)
                .eq(ImsBillHeader::getBillStatus, "1")
                .ge(ImsBillHeader::getBillDate, startTime);

        // 执行查询并求和
        List<ImsBillHeader> imsBillHeaders = imsBillHeaderMapper.selectList(queryWrapper);
        if (imsBillHeaders.isEmpty()) {
            return 0L;
        }
        // 获取总和
        return imsBillHeaders.stream().map(ImsBillHeader::getOrderNum).reduce(Long::sum).get();
    }
    public BigDecimal getMonthlyPurchases(String billType, LocalDateTime startTime, LocalDateTime endTime) {
        // 创建查询包装器
        LambdaQueryWrapper<ImsBillHeader> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ImsBillHeader::getBillType, billType)
                .ge(ImsBillHeader::getBillDate, startTime)
                .eq(ImsBillHeader::getBillStatus, "1")
                .le(ImsBillHeader::getBillDate, endTime);

        return imsBillHeaderMapper.selectList(queryWrapper).stream()
                .map(ImsBillHeader::getOrderAmount) // 获取每个订单的总金额
                .reduce(BigDecimal.ZERO, BigDecimal::add); // 计算总和
    }




}
